// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: leon

#pragma once

#include <memory>
#include <string>

#include "coin2/exchange/base/symbology/currency.h"
#include "coin2/exchange/base/symbology/util.h"

namespace coin2::exchange::deribit_index::symbology {

class DeribitCurrency
    : public base::symbology::Currency,
      public base::symbology::CurrencyFromStrMixin<DeribitCurrency> {
 public:
  using ExchangeType = base::market::ExchangeType;
  using Currency = base::symbology::Currency;
  using base::symbology::Currency::native_currency;

 public:
  explicit DeribitCurrency(const std::string& currency)
      : Currency(currency, ToNativeCurrency(currency).value(),
                 ExchangeType::Deribit) {}

  static std::unique_ptr<DeribitCurrency> FromNativeStrImpl(
      const std::string& native_currency_str, int64_t resolve_timestamp) {
    auto currency = FromNativeCurrency(
        native_currency_str, resolve_timestamp);
    if (currency) {
      return std::make_unique<DeribitCurrency>(currency.value());
    }
    return {};
  }

  static std::unique_ptr<DeribitCurrency> FromNormStrImpl(
      const std::string& currency_str, int64_t resolve_timestamp) {
    auto native_currency = ToNativeCurrency(currency_str);
    if (!native_currency) {
      return {};
    }

    auto norm_currency = FromNativeCurrency(
        *native_currency, resolve_timestamp);
    if (!norm_currency) {
      return {};
    }
    return std::make_unique<DeribitCurrency>(norm_currency.value());
  }

 public:
  static std::optional<std::string> ToNativeCurrency(
      const std::string& currency_str) {
    if (currency_str == "BCHABC" ||
        currency_str == "BCHN") {
      return "bch";
    }

    std::string native_currency_str;
    native_currency_str = StringToLowerCopy(currency_str);
    return native_currency_str;
  }

  static std::optional<std::string> FromNativeCurrency(
      const std::string& native_currency_str, int64_t resolve_timestamp) {
    if (StringIsUpper(native_currency_str)) {
      return {};
    }

    std::string currency_str;
    if (native_currency_str == "bch") {
      if (resolve_timestamp >= base::symbology::BCHA_BCHN_FORK_TIME) {
        currency_str = "BCHN";
      } else {
        currency_str = "BCHABC";
      }
    } else {
      currency_str = StringToUpperCopy(native_currency_str);
    }
    return currency_str;
  }
};

}  // namespace coin2::exchange::deribit_index::symbology
